#include "memserializer.h"
static INLINE _str_len(const char* s) {
    const char* t = s;
    if (s == NULL) {
        return 0;
    }
    while (*t++);
    return t - s - 1;
}
/*
 * Function
      Serialize the data format specified by format into buff
 * Parameters
      buff
      format: specify the format
            Data Format:
      b -> byte, B array bytearry_t data type
      w -> u16 little endian, W big endian
      d -> u32 little endian, D big endian
      s -> const char*
      S -> const char with no length*
 * Mark:
      _ -> For bytearray_t types, add 2 bytes of leading length
 */
int memvserializer(u8* buff, const char* format,  va_list argp)
{
    int index = 0;
    int count = 0;
    int pre_len = 0;
    u32 val = 0;
    int len = 0;
    const char* s = NULL;

    GUS2_UNUSE(pre_len);
    while(*format)
    {
        switch(*format)
        {
        case 'b':
            {
                val = (u8)va_arg(argp, u32);
                buff[index++] = (u8) (val & 0Xff);
            }
            break;
        case 'w':
            {
                val = (u16)va_arg(argp, u32);
                buff[index++] = (u8) (val & 0xFF);
                buff[index++] = (u8) ((val >> 8) & 0xFF);
            }
            break;
        case 'W':
            {
                val  = (u16)va_arg(argp, u32);
                buff[index++] = (u8) ((val >> 8) & 0xFF);
                buff[index++] = (u8) (val & 0xFF);
            }
            break;
        case 'D':
            {
                val  = (u32)va_arg(argp, u32);
                buff[index++] = (u8)(val >> 24);
                buff[index++] = (u8)(val >> 16);
                buff[index++] = (u8)(val >> 8);
                buff[index++] = (u8)(val >> 0);
            }
            break;
        case 'd':
            {
                val  = (u32)va_arg(argp, u32);
                buff[index++] = (u8)(val >> 0);
                buff[index++] = (u8)(val >> 8);
                buff[index++] = (u8)(val >> 16);
                buff[index++] = (u8)(val >> 24);
            }
            break;
        case 's':
            {
                s = va_arg(argp, const char*);
                len = _str_len(s);
                buff[index++] = (u8)(len >> 0);
                buff[index++] = (u8)(len >> 8);
                while (*s) {
                    buff[index++] = *s++;
                }
            }
            break;
        case 'S':
            {
                s = va_arg(argp, const char*);
                while (*s) {
                    buff[index++] = *s++;
                }
            }
            break;
        default:
            {
                if(*format <= '9' && *format >= '0')
                {
                    count += count * 10 + (*format - '0');
                }
                else if (*format == '_')
                {
                    pre_len = 1;
                }
            }
        }
        format++;
    }
    return index;
}

int memserializer(u8* buff, const char* format, ...)
{
    int index = 0;
    va_list argp;
    va_start(argp, format);
    index = memvserializer(buff, format, argp);
    va_end(argp);
    return index;
}

int memvunserializer(const u8* buff, const char* format,va_list argp)
{
    int index = 0;
    u8*  byt = NULL;
    u16* wrd = NULL;
    u32* dwrd = NULL;
    char* str = NULL;
    u16 len = 0;
    int i = 0;
    while (*format)
    {
        switch (*format)
        {
        case 'b':
            byt = (u8*) va_arg(argp, u8*);
            *byt = buff[index++];
            break;
        case 'w':
            wrd = (u16*) va_arg(argp, u16*);
            *wrd = buff[index+1];
            *wrd = ((*wrd) << 8) | buff[index+0];
            index += 2;
            break;
        case 'W':
            wrd = (u16*) va_arg(argp, u16*);
            *wrd = buff[index+0];
            *wrd = ((*wrd) << 8) | buff[index+1];
            index += 2;
            break;
        case 'D':
            dwrd = (u32*) va_arg(argp, u32*);
            *dwrd = buff[index + 0];
            *dwrd = (*dwrd << 8) | buff[index + 1];
            *dwrd = (*dwrd << 8) | buff[index + 2];
            *dwrd = (*dwrd << 8) | buff[index + 3];
            index += 4;
            break;
        case 'd':
            dwrd = (u32*) va_arg(argp, u32*);
            *dwrd = buff[index + 3];
            *dwrd = (*dwrd << 8) | buff[index + 2];
            *dwrd = (*dwrd << 8) | buff[index + 1];
            *dwrd = (*dwrd << 8) | buff[index + 0];
            index += 4;
            break;
        case 's':
            str = va_arg(argp, char*);
            len = buff[index+1];
            len = (len << 8) | buff[index+0];
            index += 2;
            for (i = 0; i < len; i++)
            {
                str[i] = buff[index++]; 
            }
            str[i] = '\0';
            len = 0;
            break;
        case 'S':
            str = va_arg(argp, char*);
            for (i = 0; i < len; i++)
            {
                str[i] = buff[index++]; 
            }
            str[i] = '\0';
            len = 0;
            break;
        default:
            {
                if(*format <= '9' && *format >= '0')
                {
                    len += len * 10 + (*format - '0');
                }
            }
            break;
        }
        format++;
    }
    return index;
}
int memunserializer(const u8* buff, const char* format, ...)
{
    int index = 0;
    va_list argp;
    va_start(argp, format);
    index = memvunserializer(buff, format, argp);
    va_end(argp);
    return index;
}

